package com.example.movie.mate.web;

import com.example.movie.mate.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.StringJoiner;

/**
 * 全局异常处理器类
 * 用于统一处理项目中抛出的异常，返回统一的错误响应格式
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理ServiceException异常的方法
     * 当服务层抛出ServiceException时，该方法会被调用，返回具体的错误信息
     *
     * @param e ServiceException异常对象，包含异常信息和错误码
     * @return JsonResult对象，封装了错误码和错误信息
     */
    @ExceptionHandler
    public JsonResult<Void> handleServiceException(ServiceException e) {
        log.debug("服务器发生ServiceException：", e);
        return JsonResult.fail(e.getCode(), e.getMessage());
    }

    @ExceptionHandler
    public JsonResult<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.debug("服务器发生MethodArgumentNotValidException：", e);
        StringJoiner errorMessage = new StringJoiner(", ");
        List<FieldError> fieldErrors = e.getFieldErrors();
        for (FieldError fieldError : fieldErrors) {
            errorMessage.add(fieldError.getDefaultMessage());
        }
        return JsonResult.fail(StateCode.ERROR_INTERNAL, errorMessage.toString());
    }

    /**
     * <p>处理Throwable异常的方法</p>
     * <p>当发生Throwable类型异常时，该方法会被调用，返回通用的内部错误信息</p>
     * <p><b>注意：</b>这个方法仅用于避免响应未经处理的错误信息到客户端，并不是正确处理异常的方式，当开发人员看到这个方法被执行时，应该在全局异常处理器中添加精准处理异常的方法</p>
     *
     * @param e Throwable对象，包含异常信息
     * @return JsonResult对象，封装了内部错误码和错误信息
     */
    @ExceptionHandler
    public JsonResult<Void> handleThrowable(Throwable e) {
        log.error("服务器发生Throwable，需进一步处理：", e);
        return JsonResult.fail(StateCode.ERROR_INTERNAL, "服务器忙，请稍后再试");
    }

}

